package com.sky.service.impl;

import com.alibaba.druid.sql.visitor.functions.If;
import com.sky.dto.GoodsSalesDTO;
import com.sky.entity.Orders;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.ReportService;
import com.sky.vo.OrderReportVO;
import com.sky.vo.SalesTop10ReportVO;
import com.sky.vo.TurnoverReportVO;
import com.sky.vo.UserReportVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.awt.peer.LightweightPeer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ReportServiceImpl implements ReportService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private UserMapper userMapper;

    /**
     * 返回我们的营业额 根据我们指定的时间段
     * (本质是调用mapper后 处理数据封装vo)
     * 可以看vo需要哪些表 分开处理 后拼接 也可以直接多表查询
     * @param begin
     * @param end
     * @return
     */
    @Override
    public TurnoverReportVO statistics(LocalDate begin, LocalDate end) {
        //这里我们可以把每天的订单的全部price sum一下 然后就可以获得一天的营业额
        //这里我们要先计算一下 我们的dateList 我们怎么通过前段响应的两个localdate 属性 计算出我们的datelist(注意 每一天都包含且为String)
        List<LocalDate> dateList = new ArrayList<>();
        //这里我们要计算出从开始到结束的每天计算
        dateList.add(begin);
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);
            dateList.add(begin);
        }
        List<Double> turnoverList=new ArrayList<>();
        for (LocalDate date : dateList) {
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            Map map=new HashMap();
            map.put("begin",beginTime);
            map.put("end",endTime);
            map.put("status", Orders.COMPLETED);
           Double turnover=orderMapper.sumbymap(map);
            turnover = turnover == null ? 0.0 : turnover;
            turnoverList.add(turnover);
        }


        return TurnoverReportVO.builder().dateList(StringUtils.join(dateList, ",")).turnoverList(StringUtils.join(turnoverList,",")).build();
    }

    /**
     * 用户统计(注意这里我们包含两个数据 一个是用户新增 一个是我们的用户总数)
     * @param begin
     * @param end
     * @return
     */
    @Override
    public UserReportVO userStatiscs(LocalDate begin, LocalDate end) {
        //在这里我们就使用我们的构建器来构建我们的数据
        //计算dateList
        List<LocalDate> dateList = new ArrayList<>();
        dateList.add(begin);
        //注意这里我们的类重写了equals方法 这样我们比较才是比较我们的属性值
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);
            dateList.add(begin);
        }
        //计算totalList(计算每日总共)
        List<Integer> totalList = new ArrayList<>();

        //我们可以通过动态SQL来兼容我们的这两个查找(聚合函数
        //注意我们的user表中设计了create_time 我们可以通过这个时间来查看我们的user

        //计算newUserList(计算每日新增) 通过create_time来计算我们的时间段（可以查出来不同天的然后相减就得到了新增的）
        List<Integer> newuserList=new ArrayList<>();
        for (LocalDate date : dateList) {
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            Map totalmap=new HashMap();
            Map usermap=new HashMap();
            usermap.put("begin",beginTime);
            usermap.put("end",endTime);
            totalmap.put("end",endTime);
            Integer total = userMapper.countbymap(totalmap);
            Integer user = userMapper.countbymap(usermap);
            totalList.add(total);
            newuserList.add(user);
            //注意新增员工就是每天的用户变化数   总员工只需要截止每天的最后就可以了
        }
        return UserReportVO.builder().dateList(StringUtils.join(dateList,",")).totalUserList(StringUtils.join(totalList,",")).newUserList(StringUtils.join(newuserList,",")).build();
    }

    /**
     * 订单统计
     * @param begin
     * @param end
     * @return
     */
    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
        //这里我们分析怎么查询我们需要的对应数据
        List<LocalDate> dateList = new ArrayList<>();
        dateList.add(begin);
        //日期列表
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);
            dateList.add(begin);
        }
        //注意这里按我们VO的数据类型封装
        //这里就是我们对应的总订单列表和我们的有效订单表
        List<Integer> totalList = new ArrayList<>();
        List<Integer> finishList=new ArrayList<>();
        //这里我们的for效率很低 我们是否能编写不一样的SQL进行优化呢?(分组+聚合？)
        for (LocalDate date : dateList) {
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            //查询订单总数  查询有效订单数(每天) 然后我们的全部可以直接用每天求和(通过一个动态的SQL就可以解决了)
            Map map=new HashMap();
            map.put("begin",beginTime);
            map.put("end",endTime);
            //这里还没有限制条件
            Integer daytotal=orderMapper.getOrders(map);
            totalList.add(daytotal);
            map.put("status", Orders.COMPLETED);
            Integer finish=orderMapper.getOrders(map);
            finishList.add(finish);
        }
        //然后完成率就使用有效(状态为完成)/总数
        //这里的有效订单数和订单总数直接使用列表的api计算
        Integer totalOrderCount= totalList.stream().reduce(Integer::sum).get();
        Integer validOrderCount=finishList.stream().reduce(Integer::sum).get();
        Double orderCompletionRate=0.0;
        if(totalOrderCount!= 0) {
             orderCompletionRate = validOrderCount.doubleValue() / totalOrderCount;
        }
        return OrderReportVO.builder()
                .dateList(StringUtils.join(dateList, ","))
                .totalOrderCount(totalOrderCount)
                .validOrderCount(validOrderCount)
                .orderCompletionRate(orderCompletionRate)
                .orderCountList(StringUtils.join(totalList, ","))
                .validOrderCountList(StringUtils.join(finishList, ","))
                .build();
    }

    /**
     * 查询销量前十菜品
     * (一个是order_details 这个表去查具体的数据)
     * (还有一个就去查我们的订单表(查time))
     * @param begin
     * @param end
     * @return
     */
    @Override
    public SalesTop10ReportVO SalesTop10Statiscs(LocalDate begin, LocalDate end) {
        //注意这里我们只统计完成的订单中我们的销量  强化我们的SQL  聚合函数+字段 实现分组的作用(然后查询到我们的数据之后封装)
        //这里为我们设置了接收我们封装数据的DTO(最好命名为entity更好)
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);
        List<GoodsSalesDTO> top = orderMapper.getTop(beginTime, endTime);
        SalesTop10ReportVO salesTop10ReportVO = new SalesTop10ReportVO();
        List<String> namelist = new ArrayList<>();
        List<Integer> numberlist = new ArrayList<>();
        for (GoodsSalesDTO goodsSalesDTO : top) {
            namelist.add(goodsSalesDTO.getName());
            numberlist.add(goodsSalesDTO.getNumber());
        }
        salesTop10ReportVO.setNameList(StringUtils.join(namelist, ","));
        salesTop10ReportVO.setNumberList(StringUtils.join(numberlist, ","));
        return salesTop10ReportVO;
    }

}
